package com.vshop.timingtask;


import com.vshop.entity.agatewaytobeijing.JsonConstant;
import com.vshop.entity.agatewaytobeijing.Page;
import com.vshop.entity.agatewaytobeijing.syncdevice.response.DevicePackageList;
import com.vshop.entity.agatewaytobeijing.syncdevice.response.OriginalDevicePackage;
import com.vshop.entity.agatewaytobeijing.syncdevice.response.ResponseSynchronizeDevice;
import com.vshop.entity.agatewaytobeijing.syncdevice.response.SynchronizeDeviceData;
import com.vshop.entity.comentity.PartnerInfo;
import com.vshop.service.agatewaytobeijing.GatewayToBeijingService;
import com.vshop.service.task.ServicePlanTaskServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

/**
 * 同步设备
 *
 * @author lm
 * @date 2020/11/3 10:58
 */
@Configuration
@EnableScheduling
@RestController
@Slf4j
public class SyncDeviceNewTask {
    @Value("${system.autoTask}")
    private boolean autoTask;
    @Autowired
    ServicePlanTaskServiceImpl taskService;
    @Autowired
    GatewayToBeijingService toBeijingService;


    @Scheduled(cron = " 0 2 22 * * ?")
    @Async
    @GetMapping(value = "device")
    public void execute() {
        if (autoTask) {
            syncDeviceTask();
        }
    }

    public void syncDeviceTask() {

        log.info("每1天晚上22点执行一次的syncDeviceTask开始执行！");
        //1，取数据库取需要去同步套餐的partnerCode出来,方便可以使用某个固定的企业查询，这边加个参数,""就是取所有
        List<PartnerInfo> partnerList = taskService.findPartnerCode("");

        for (PartnerInfo partner : partnerList) {

            boolean b1 = StringUtils.isBlank(partner.getPartnerCode()) || StringUtils.isBlank(partner.getSecret()) || StringUtils.isBlank(partner.getPartnerName());
            if (b1) {
                continue;
            }

            //现在去数据库比对当前partnerCode是否是需要去同步套餐和设备的,如果在列表中有记录可以理解返回
            if (taskService.queryOrNotPartnerCode(partner.getPartnerCode()) >= 1) {
                log.info(partner.getPartnerCode() + "：无需请求列表企业");
                continue;
            }

            //把有用的参数拿出来
            String partnerCode = partner.getPartnerCode();
            String secret = partner.getSecret();
            String partnerName = partner.getPartnerName();
            Integer partnerIndex = Integer.parseInt(partner.getPartnerIndex());

            //第一次去请求确定有多少个套餐确定循环需要做多少次
            ResponseSynchronizeDevice firstRequest = toBeijingService.synchronizeDevice(1, 1, partnerCode, secret);

            //先验证请求结果的response：如果返回的是""就可以直接返回了
            if (StringUtils.isBlank(checkResponseSynchronizeDevice(firstRequest))) {
                continue;
            }

            /*1000条每次：直接取page的值，拿到一共有多少条数据 去计算需要去执行几次请求*/
            double total = taskService.countExecutionTimes(firstRequest.getData().getPage());
            /*500条每次：double total = taskService.countExecution(firstRequest.getData().getPage());*/
            //用一个允许控制执行请求的次数
            for (int x = 1; x <= total; x++) {

                log.info("企业是：" + partnerCode + ";一共：" + firstRequest.getData().getPage().getTotal_count() + "条记录;需执行：" + total + "次;当前是：第" + x + "次");

                //第二次去请求要获得真正的套餐信息
                ResponseSynchronizeDevice secondRequest = toBeijingService.synchronizeDevice(x, 1000, partnerCode, secret);

                //先验证请求结果的response：如果返回的是""就可以直接返回了
                if (StringUtils.isBlank(checkResponseSynchronizeDevice(secondRequest))) {
                    break;
                }

                //开始遍历设备的可购套餐列表信息
                for (OriginalDevicePackage originalDevice : secondRequest.getData().getDevice_packages()) {

                    if (StringUtils.isBlank(originalDevice.getDevice_id()) || null == originalDevice.getPackages()) {
                        continue;
                    }

                    if (StringUtils.isBlank(originalDevice.getPackages().getPackage_num() + "") || null == originalDevice.getPackages().getPackage_list()) {
                        continue;
                    }

                    if (null == originalDevice.getPackages().getPackage_list()) {
                        continue;
                    }
                    DevicePackageList package_list = originalDevice.getPackages().getPackage_list();

                    if (null == package_list.getPackage_code() || package_list.getPackage_code().isEmpty()) {
                        continue;
                    }
                    List<String> codeList = package_list.getPackage_code();

                    //现在去解：package_code返回是这个样子的：["DP20181102000178", "DP20181106000186", "DP20190321000503"]
                    for (String packageCode : codeList) {

                        if (StringUtils.isBlank(packageCode)) {
                            continue;
                        }
                        //套餐名称
                        String packageName = taskService.queryPackageNameByCode(partnerCode, packageCode);
                        //没有套餐名称的不允许入库
                        if (StringUtils.isBlank(packageName)) {
                            continue;
                        }

                        //根据索引去不同的数据表查询数据表有没有这个设备和套餐的对应关系数据，有就循环继续，没有就入库
                        dealDevicePackagesRelation(partnerIndex, partnerCode, partnerName, packageCode, packageName, originalDevice.getDevice_id());
                        //这边结果不管是什么都是要继续continue的，所以不判断也行
                    }
                }

            }
        }
        log.info("每1天晚上22点执行一次的syncDeviceTask执行完毕");
    }

    /**
     * 验证请求后的响应 ResponseSynchronizeDevice
     *
     * @param response
     * @return
     */
    private String checkResponseSynchronizeDevice(ResponseSynchronizeDevice response) {

        //response响应就是null
        if (null == response) {
            return "";
        }

        //返回的具体的内容是空的或者没有
        if (StringUtils.isBlank(response.getCode()) || StringUtils.isBlank(response.getMessage())) {
            return "";
        }

        //返回的内容不是成功
        boolean b1 = (!JsonConstant.RET_CODE_0000.equals(response.getCode()) && !JsonConstant.RET_CODE_SUCCESS.equals(response.getMessage())) || null == response.getData();
        if (b1) {
            log.info("【同步设备套餐关系】响应：" + response.getCode() + ";提示：" + response.getMessage());
            return "";
        }

        SynchronizeDeviceData data = response.getData();
        if (null == data.getPage() || null == data.getDevice_num() || null == data.getDevice_packages() || data.getDevice_packages().isEmpty()) {
            return "";
        }

        Page page = data.getPage();
        if (StringUtils.isBlank(page.getTotal_count() + "") || page.getTotal_count() <= 0) {
            return "";
        }
        //验证没有问题
        return JsonConstant.RET_CODE_SUCCESS;
    }

    /**
     * 处理设备和套餐的对应关系数据：
     * <p>
     * 1,查询有没有判断是否需要入库
     * 2,1中结果是没有才有第2步入库
     *
     * @param partnerIndex
     * @param partnerCode
     * @param partnerName
     * @param packageCode
     * @param packageName
     * @param deviceCode
     * @return
     */
    public Integer dealDevicePackagesRelation(Integer partnerIndex, String partnerCode, String partnerName, String packageCode, String packageName, String deviceCode) {

        Integer result = 0;

        //数据表的名称
        String tableName = "partner_device_packages_relation_t_" + partnerIndex + "";
        //查询对应的数据表里面有没有这条记录
        Integer count = taskService.findCountByCondition(tableName, partnerCode, packageCode, deviceCode);
        if (count >= 1) {
            //说明数据库已经有这条数据了，直接返回就行了
            return count;
        }

        //没有数据就去入库
        Integer insertCount = taskService.storageRelation(tableName, partnerCode, partnerName, packageCode, packageName, deviceCode);
        if (insertCount >= 1) {
            return insertCount;
        }
        return result;
    }

}
